﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

// extra headers added
using System.IO;
using System.Xml;

// MATLAB additions
using MathWorks.MATLAB.NET.Utility;
using MathWorks.MATLAB.NET.Arrays;
using fromMatlab;

namespace XML_Clustering
{
    public partial class Form1 : Form
    {
        private double[,] plotValues;
        private int length;
        private string[] fileEntries;

        // creating a new matlab object
        fromMATLAB fm;

        public Form1()
        {
            InitializeComponent();

            // To initialize the MATLAB object
            fm = new fromMATLAB();
        }

        private int xmlElementCount(string filelocation)
        {
            int count = 0;
            // Set the validation settings.
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.ProhibitDtd = false;
            XmlReader read_xml = XmlReader.Create(filelocation,settings);
            try
            {
                while (read_xml.Read())
                {
                    if (read_xml.NodeType == XmlNodeType.Element)
                    {
                        count++;
                    }
                }
            }
            catch (Exception es)
            {
                // for now, just ignoring them.
            }
            return count;
        }

        private int xmlMaxDepth(string filelocation)
        {
            int depth = 0;
            // Set the validation settings.
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.ProhibitDtd = false;
            XmlReader read_xml = XmlReader.Create(filelocation, settings);
            try
            {
                while (read_xml.Read())
                {
                    if (read_xml.Depth > depth)
                        depth = read_xml.Depth;
                }
            }
            catch (Exception es)
            {
                // for now, just ignoring them.
            }
            return depth;
        }

        private void openDirectoryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            int NumElements;
            int XmlDepth;
            int numPoints=0; // the number of points to plot
            // Need to ask the user to select a folder at this point
            folderBrowserDialog1.SelectedPath = Directory.GetCurrentDirectory();
            folderBrowserDialog1.ShowDialog();
            if (folderBrowserDialog1.SelectedPath != null)
            {
                textBox1.Text = folderBrowserDialog1.SelectedPath;


                // Now we'll need to scan the directory for XML files 
                // and display them in the listView control

                // First, get the list of XML files
                fileEntries = Directory.GetFiles(textBox1.Text, "*.xml");

                // now to show them in the listview control
                length = fileEntries.Length;
                numPoints = length;
                // Allocate native array for plot values
                plotValues = new double[4, numPoints];

                ListViewItem item;
                for (int i = 0; i < length; i++)
                {
                    item = new ListViewItem(Path.GetFileName(fileEntries[i]), 0); // just the file names
                    // now some basic info about the file
                    FileInfo fi = new FileInfo(fileEntries[i]);
                    item.SubItems.Add(Convert.ToString(fi.Length)); // the size of the file

                    // on one axis, the length
                    plotValues[0,i] = fi.Length;

                    NumElements = xmlElementCount(fileEntries[i]);

                    // on the other axis, the number of elements
                    plotValues[1, i] = NumElements;
                    item.SubItems.Add(Convert.ToString(NumElements));

                    // To find depth of XML file
                    XmlDepth = xmlMaxDepth(fileEntries[i]);
                    plotValues[2, i] = XmlDepth;
                    item.SubItems.Add(Convert.ToString(XmlDepth));

                    // Filling in a dummy "cluster" value
                    plotValues[3, i] = 0;
                    item.SubItems.Add(Convert.ToString(0));

                    // add the into the listview
                    listView1.Items.Add(item);
                }

              
            }
            else
            {
                // if it was NULL nothing to do
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // The exit button
            Application.Exit();
        }

        private void plotDataToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // we'll show the matlab plot here
            // for now assuming that this is running AFTER data has been obtained

            //// creating a new matlab object
            //fromMATLAB fm = new fromMATLAB();

            // now to call the plot
            fm.drawgraph3((MWNumericArray)plotValues);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // Make a new stopwatch object for timing analysis
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

            // clear textbox
            textBox3.Clear();

            // start !
            sw.Start();

            // Need to run the clustering algorithm from here

            // first find the number of clusters needed
            double cl_num = (double)numericUpDown1.Value;

            //// creating a new matlab object
            //fromMATLAB fm = new fromMATLAB();

            // now to call the clustering algorithm
            MWNumericArray argsOut = (MWNumericArray)fm.ASSIGN_CLUSTER((MWNumericArray)plotValues, cl_num);

            double[,] result = (double[,])argsOut.ToArray(MWArrayComponent.Real);

            // stop stopwatch
            sw.Stop();

            // display times
            textBox3.Text = sw.ElapsedMilliseconds.ToString();

            for(int i =0;i<length;i++)
            {
                plotValues[3, i] = result[0,i];
            }

            // Now to re-draw the clustering table
            listView1.Items.Clear();
            ListViewItem item;
            for (int i = 0; i < length; i++)
            {
                item = new ListViewItem(Path.GetFileName(fileEntries[i]), 0); // just the file names
                item.SubItems.Add(Convert.ToString(plotValues[0, i])); // the size of the file
                item.SubItems.Add(Convert.ToString(plotValues[1, i]));
                item.SubItems.Add(Convert.ToString(plotValues[2, i]));
                item.SubItems.Add(Convert.ToString(plotValues[3, i]));
                // add the into the listview
                listView1.Items.Add(item);
            }


        }

        private void destinationDirectoryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Need to ask the user to select a folder to dump output at this point
            folderBrowserDialog1.SelectedPath = Directory.GetCurrentDirectory();
            folderBrowserDialog1.ShowDialog();
                
            textBox2.Text = folderBrowserDialog1.SelectedPath;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            // open the XML source folder in explorer
            System.Diagnostics.Process.Start("explorer.exe", textBox1.Text );
        }

        private void button3_Click(object sender, EventArgs e)
        {
            // open the XML clustered folder in explorer
            System.Diagnostics.Process.Start("explorer.exe", textBox2.Text);
        }

        private void button4_Click(object sender, EventArgs e)
        {
            // we first need to make new sub-directories for moving the clusterd files to,
            for (int i = 0; i <= numericUpDown1.Value; i++)
            {
                // NOTE: 0 should NOT be used as part of clustering - it's just there in-case someone forgot
                // to run the clustering algorithm in the first place.
                string newPath = Path.Combine(textBox2.Text, i.ToString());
                // the new sub-directories
                Directory.CreateDirectory(newPath);
            }

            // We'll assume that the clustering is already done

            // Need a loop to move through all the files
            for (int i = 0; i < length; i++)
            {
                string sourcePath = fileEntries[i];
                string targetPath = Path.Combine(textBox2.Text, plotValues[3, i].ToString());
                targetPath = Path.Combine(targetPath, Path.GetFileName(fileEntries[i]));
                // copy the file over
                File.Copy(sourcePath, targetPath, true); // true means to over-write the file if it
                                                         // exists in destination
            }
        }

        private void button5_Click(object sender, EventArgs e)
        {
            // Will plot the clustered data in a single plot here

            //// creating a new matlab object
            //fromMATLAB fm = new fromMATLAB();

            // find the number of clusters needed
            double cl_num = (double)numericUpDown1.Value;

            // now to call the plot
            fm.clusterplot((MWNumericArray)plotValues, cl_num);            
        }

        private void button6_Click(object sender, EventArgs e)
        {
            // Make a new stopwatch object for timing analysis
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

            // clear textbox
            textBox3.Clear();

            // start !
            sw.Start();

            // Need to edit the values to normalize them. Will just do it in a loop
            for (int i = 0; i <= 2; i++)
            {
                double min, max, range;

                // staring stage
                min = plotValues[i, 0];
                max = plotValues[i, 0];
                // now loop to find the actual values
                for (int j = 0; j < length; j++)
                {
                    if (min > plotValues[i, j])
                        min = plotValues[i, j];
                    if (max < plotValues[i, j])
                        max = plotValues[i, j];
                }
                range = max - min;

                // now to loop and normalize the values
                for (int j = 0; j < length; j++)
                {
                    // The "* 100" below is to just normalize the values to between 0 and 100
                    // Change it to "1" for it to be the EXACT algorithm in the paper
                    plotValues[i, j] = (plotValues[i, j] - min) / range;
                }
            }

            // stop stopwatch
            sw.Stop();

            // display times
            textBox3.Text = sw.ElapsedMilliseconds.ToString();

            // Normalization done, now to show the update the table for user
            listView1.Items.Clear();
            ListViewItem item;
            for (int i = 0; i < length; i++)
            {
                item = new ListViewItem(Path.GetFileName(fileEntries[i]), 0); // just the file names
                item.SubItems.Add(Convert.ToString(plotValues[0, i])); // the size of the file
                item.SubItems.Add(Convert.ToString(plotValues[1, i]));
                item.SubItems.Add(Convert.ToString(plotValues[2, i]));
                item.SubItems.Add(Convert.ToString(plotValues[3, i]));
                // add the into the listview
                listView1.Items.Add(item);
            }
        }

    }
}
